

import React, { CSSProperties, ReactNode, useCallback, useEffect, useMemo } from 'react'
import './Keyboard.css'
import SubMonitor from './SubMonitor'
import { gRegisterDevice, KASEO_MAIN, SESSION_ID } from '../../../KaseoApp';
import KaseoKeyboardDI from '../../runtime/dev/KaseoKeyboardDI';


let keyIdCount = 128;


interface KeyExtData {
    style?: CSSProperties
    clsName?: string
    id?: number
}


const extKeyButtons = [
    ['(', ')', '[', ']', ',', '\'', '"', '='],
    ['?', '&', '^', '%', '$', '#', '@', '!'],
]

const numpadKeys = [
    ['7', '8', '9', 'DEL', 'AC'],
    ['4', '5', '6', '×', '÷'],
    ['1', '2', '3', '+', '-'],
    ['0', '.', 'x10', '( - )', 'EXE']
]

const keyExtData: { [key: string]: KeyExtData } = {
    'DEL': { clsName: 'kaseo-key-btn-special', id: keyIdCount++},
    'AC': { clsName: 'kaseo-key-btn-special', id: keyIdCount++},
    'x10': { id: keyIdCount++ },
    '( - )': { id: keyIdCount++ },
    'EXE': { id: keyIdCount++ },
    '×': { id: '*'.charCodeAt(0) },
    '÷': { id: '/'.charCodeAt(0) },
}

function NavKey(props: { keyboardDI?: KaseoKeyboardDI }) {
    const onMouseDown = useCallback((keyId: number, label: string) => {
        props.keyboardDI?.setKeyState(keyId, true)
        console.log('down: ' + keyId + ' ' + label)
    }, [])

    const onMouseUp = useCallback((keyId: number, label: string) => {
        props.keyboardDI?.setKeyState(keyId, false)
        console.log('up: ' + keyId + label)
    }, [])

    const upId = useMemo(() => keyIdCount++, []);
    const rightId = useMemo(() => keyIdCount++, []);
    const downId = useMemo(() => keyIdCount++, []);
    const leftId = useMemo(() => keyIdCount++, []);

    return (
        <div className='kaseo-key-nav'>
            <div className='kaseo-key-nav-bg'>
                {keyIdCount++ && !undefined}
                <div
                    onMouseDown={() => onMouseDown(upId, '<UP>M')}
                    onMouseUp={() => onMouseUp(upId, '<UP>M')}
                    className='kaseo-key-nav-btn' style={{ left: '26px', top: '-5px' }}>
                    {'▲'}
                </div>

                <div
                    onMouseDown={() => onMouseDown(downId, '<DOWN>M')}
                    onMouseUp={() => onMouseUp(downId, '<DOWN>M')}
                    className='kaseo-key-nav-btn' style={{ left: '27px', top: '30px' }}>
                    {'▼'}
                </div>

                <div
                    onMouseDown={() => onMouseDown(leftId, '<LEFT>M')}
                    onMouseUp={() => onMouseUp(leftId, '<LEFT>M')}
                    className='kaseo-key-nav-btn' style={{ top: '-30px', left: '-5px' }}>
                    {'◀'}
                </div>

                <div
                    onMouseDown={(e) => onMouseDown(rightId, '<RIGHT>M')}
                    onMouseUp={(e) => onMouseUp(rightId, '<RIGHT>M')}
                    className='kaseo-key-nav-btn' style={{ left: '60px', top: '-60px' }}>
                    {'▶'}
                </div>
            </div>
        </div>
    )
}

function KeyButton(props: {
    label: string,
    keyId: number,
    numpad?: boolean,
    margin?: boolean,
    ext?: KeyExtData,
    keyboardDI?: KaseoKeyboardDI
}) {
    let ext = props.ext
    if (!ext)
        ext = { style: {} }

    const onMouseDown = useCallback(() => {
        props.keyboardDI?.setKeyState(props.keyId, true)
        console.log('down: ' + props.keyId)
    }, [props.keyId])

    const onMouseUp = useCallback(() => {
        props.keyboardDI?.setKeyState(props.keyId, false)
        console.log('up: ' + props.keyId)
    }, [props.keyId])

    return (
        <div
            onMouseDown={onMouseDown}
            onMouseUp={onMouseUp}
            className={"kaseo-key-button " + (props.numpad ? 'kaseo-key-btn-np' : 'kaseo-key-btn-ext') + ` ${props.ext?.clsName ? props.ext?.clsName : ''}`}
            style={{ ...{ marginTop: props.margin ? '5px' : '0px' }, ...ext.style }}>

            {props.label}
        </div>
    )
}


function KeyRow(props: { children?: ReactNode }) {
    return (
        <div className='kaseo-keyboard-row'>
            {props.children}
        </div>
    )
}


export default function Keyboard(props: {
    onKeyDown?: (keyId: string) => void,
    style?: CSSProperties
}) {

    const DI = useMemo(() => new KaseoKeyboardDI, [SESSION_ID])

    useEffect(() => {
        gRegisterDevice(DI)
        KASEO_MAIN.registerMajorKeyboardDI(DI)
    }, [SESSION_ID])

    function calcKeyId(k: string) {
        const ext = keyExtData[k]
        return ext?.id ?? k.charCodeAt(0)
    }

    return (
        <div className="kaseo-keyboard-box" style={props.style}>
            <div className='kaseo-keyboard-func-row'>
                <SubMonitor />
                <NavKey keyboardDI={DI} />
            </div>

            {
                extKeyButtons.map((row, idx) => (
                    <KeyRow key={idx}>
                        {row.map((k, ridx) => (
                            <KeyButton
                                keyboardDI={DI}
                                label={k} keyId={calcKeyId(k)} key={idx * 6 + ridx} margin={idx != 0} ext={keyExtData[k]} />
                        ))}
                    </KeyRow>
                ))
            }

            <br />

            {
                numpadKeys.map((row, idx) => (
                    <KeyRow key={extKeyButtons.length + idx}>
                        {row.map((k, ridx) => (
                            <KeyButton
                                keyboardDI={DI}
                                label={k} keyId={calcKeyId(k)} key={extKeyButtons.length + idx * 6 + ridx} numpad
                                margin={idx != 0} ext={keyExtData[k]} />
                        ))}
                    </KeyRow>
                ))
            }
        </div>
    )
}
